package org.fujene.memoryblock.local;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.fujene.memoryblock.MemoryBlock;
import org.fujene.structure.Constants;
import org.fujene.toolbox.ByteConverter;

public class LocalContentBlock extends MemoryBlock {
	private volatile int opt_length = 0;

	public LocalContentBlock(int bodySize, int ID, boolean isAllocate) {
		super(bodySize, ID, Constants.MEMORY_TYPE_CONTENTS, isAllocate);
	}

	// 1個分の本文情報
	public class Contents {
		private int from = -1;
		private int strLength;
		private String content;

		// 情報読み出し
		public Contents(int from) {
			this.from = from;
			this.strLength = ByteConverter.byteToInt(getBody(from, STRLEN));
			from += STRLEN;
			try {
				this.content = new String(getBody(from, this.strLength),
						"UTF-8");
			} catch (UnsupportedEncodingException e) {
			}
		}

		// 読み出さない
		public Contents(int from, String str) {
			set(from, str);
		}

		public void set(String str) {
			this.content = str;
			try {
				this.strLength = str.getBytes("UTF-8").length;
			} catch (UnsupportedEncodingException e) {
			}
		}

		public void set(int from, String str) {
			this.from = from;
			set(str);
		}

		public void write() {
			// from が -1 だったら書き込まない
			if (this.from == -1)
				return;

			bodyVacancy -= STRLEN + strLength;
			opt_length++;
			int tmp = this.from;
			setBody(ByteConverter.intToByte(this.strLength, STRLEN), tmp);
			tmp += STRLEN;
			try {
				byte[] b = content.getBytes("UTF-8");
				setBody(b, tmp);
			} catch (UnsupportedEncodingException e) {
			}
		}

		public void write(int from) {
			this.from = from;
			write();
		}

		public String getContent() {
			return content;
		}
	}

	public String getContent(int ptr) {
		Contents ptred = new Contents(ptr);
		return ptred.content;
	}

	public void setContent(int ptr, String str) {
		Contents newContent = new Contents(ptr, str);
		newContent.write();
	}

	// サイズ確認なし
	public int getNewPointer() {
		return this.bodySize - this.bodyVacancy;
	}

	// サイズ確認つき
	public int getNewPointer(String str) {
		try {
			if (this.bodyVacancy >= STRLEN + str.getBytes("UTF-8").length) {
				return this.bodySize - this.bodyVacancy;
			} else {
				return -1;
			}
		} catch (UnsupportedEncodingException e) {
			return -1;
		}
	}

	public int getCount() {
		return opt_length;
	}

	@Override
	public int getOptionSize() {
		return 1;
	}

	@Override
	public byte[] getOptionByteStream() {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		
		try {
			stream.write(ByteConverter.intToByte(opt_length, 4));
		} catch (IOException e) {
		}
		return stream.toByteArray();
	}

	@Override
	public void setOption(int option, int value) {
		if (option == 0)
			opt_length = value;
	}

	@Override
	public String getClassName() {
		return new String("ContentBlock");
	}

	@Override
	public byte[] getData() throws IOException {
		throw new NoSuchMethodError("Unimplemented method");
	}

	@Override
	public void setData(byte[] array) throws IOException {
		throw new NoSuchMethodError("Unimplemented method");
	}
}
